
 <!DOCTYPE HTML>
<html >
<head>
  <meta charset="UTF-8">
  
    <title>jdk源码分析之List--常用实现类分析与对比 | Typhoon&#39;s code space</title>
    <meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
    
    <meta name="author" content="typhoon">
    

    
    <meta name="description" content="java编码中，集合类算是我们用的最多的，比如HashMap，TreeMap，ArrayList，LinkedList等等，">
<meta name="keywords" content="java性能优化">
<meta property="og:type" content="article">
<meta property="og:title" content="jdk源码分析之List--常用实现类分析与对比">
<meta property="og:url" content="http://scorpioaeolus.oschina.io/2018/04/21/list分析/index.html">
<meta property="og:site_name" content="Typhoon&#39;s code space">
<meta property="og:description" content="java编码中，集合类算是我们用的最多的，比如HashMap，TreeMap，ArrayList，LinkedList等等，">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l1.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l2.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l3.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l4.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l5.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l6.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l7.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l9.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l10.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l11.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l12.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l14.jpg">
<meta property="og:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/webchat.jpg">
<meta property="og:updated_time" content="2018-04-21T03:58:22.040Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="jdk源码分析之List--常用实现类分析与对比">
<meta name="twitter:description" content="java编码中，集合类算是我们用的最多的，比如HashMap，TreeMap，ArrayList，LinkedList等等，">
<meta name="twitter:image" content="http://scorpioaeolus.oschina.io/typhoon/2018/04/21/list分析/l1.jpg">

    
    <link rel="alternative" href="/atom.xml" title="Typhoon&#39;s code space" type="application/atom+xml">
    
    
    <link rel="icon" href="/typhoon/img/java.png">
    
    
    <link rel="apple-touch-icon" href="/typhoon/img/jacman.jpg">
    <link rel="apple-touch-icon-precomposed" href="/typhoon/img/jacman.jpg">
    
    <link rel="stylesheet" href="/typhoon/css/style.css">
</head>

  <body>
    <header>
      
<div>
		
			<div id="imglogo">
				<a href="/typhoon/"><img src="/typhoon/img/java.png" alt="Typhoon&#39;s code space" title="Typhoon&#39;s code space"/></a>
			</div>
			
			<div id="textlogo">
				<h1 class="site-name"><a href="/typhoon/" title="Typhoon&#39;s code space">Typhoon&#39;s code space</a></h1>
				<h2 class="blog-motto"></h2>
			</div>
			<div class="navbar"><a class="navbutton navmobile" href="#" title="Menu">
			</a></div>
			<nav class="animated">
				<ul>
					<ul>
					 
						<li><a href="/typhoon/">主页</a></li>
					
						<li><a href="/typhoon/archives">归档</a></li>
					
						<li><a href="/typhoon/about">关于</a></li>
					
					<li>
 					
					<form class="search" action="//google.com/search" method="get" accept-charset="utf-8">
						<label>Search</label>
						<input type="search" id="search" name="q" autocomplete="off" maxlength="20" placeholder="Search" />
						<input type="hidden" name="q" value="site:scorpioaeolus.oschina.io">
					</form>
					
					</li>
				</ul>
			</nav>			
</div>
    </header>
    <div id="container">
      <div id="main" class="post" itemscope itemprop="blogPost">
  
	<article itemprop="articleBody"> 
		<header class="article-info clearfix">
  <h1 itemprop="name">
    
      <a href="/typhoon/2018/04/21/list分析/" title="jdk源码分析之List--常用实现类分析与对比" itemprop="url">jdk源码分析之List--常用实现类分析与对比</a>
  </h1>
  <p class="article-author">By
       
		<a href="/typhoon/about" title="typhoon" target="_blank" itemprop="author">typhoon</a>
		
  <p class="article-time">
    <time datetime="2018-04-21T03:19:41.000Z" itemprop="datePublished"> Published 2018-04-21</time>
    
  </p>
</header>
	<div class="article-content">
		
		<div id="toc" class="toc-article">
			<strong class="toc-title">Contents</strong>
		
			<ol class="toc"><li class="toc-item toc-level-5"><a class="toc-link" href="#原创不易，请多多支持！"><span class="toc-number">1.</span> <span class="toc-text">原创不易，请多多支持！</span></a></li></ol>
		
		</div>
		
		<pre><code>java编码中，集合类算是我们用的最多的，比如HashMap，TreeMap，ArrayList，LinkedList等等，
</code></pre>  <a id="more"></a>
<pre><code>使我们最常用的(并发包中的实现暂不做分析)，按照顶级接口分析，有两种，就是Map和Collection(Collection接口继承于Iterable)，
Collection又分为List和Set分支，也就是列表和集合。今天我们队List分支以及其常用实现子类进行源码层面分析和对比。
List分支中我们最常用的实现有ArrayList，LinkedList和Vector(已经近乎废弃)，分析一下其继承关系：
</code></pre><img src="/typhoon/2018/04/21/list分析/l1.jpg" alt="list" title="list">
<pre><code>    可以看出AbstractList实现了List接口，ArrayList，LinkedList和Vector继承了AbstractList并且实现了List接口；
AbstractList提供了对List接口功能的一些通用实现(也就是抽象的概念，不用每个具体实现类再去实现)，而三个实现类既然继承了AbstractList，
为什么又实现List接口呢？其实是是一种既可以使用AbstractList中的通用实现，又可以对List接口提供原生的实现。
     接下来我们从List到具体实现类，详细分析一下其功能和实现：
</code></pre><img src="/typhoon/2018/04/21/list分析/l2.jpg" alt="list" title="list">
<pre><code>     从List接口中文档描述我们可以得出每个方法的具体作用：
1)int size(),返回列表中元素的数目.
2)boolean isEmpty(),返回列表中是否包含元素，如果有返回false，否则true
3)boolean contains(Object o)，返回列表中是否包含元素o，包含返回true，否则false
4)Iterator&lt;E&gt; iterator()，返回当前列表的迭代器，用于遍历列表元素
5)Object[] toArray()，将当前列表转换为数组并返回
6)&lt;T&gt; T[] toArray(T[] a)，将列表转换为给定类型的数组并返回
7)boolean add(E e)，将元素增加到列表结尾
8)boolean remove(Object o)，从列表中移除第一个匹配的元素，如果找到移除后返回true，如果没有该元素，返回false
9)boolean containsAll(Collection&lt;?&gt; c)，返回列表是否包含入参中的所有元素
10)boolean addAll(Collection&lt;? extends E&gt; c)，将入参中的所有元素添加到列表结尾
11)boolean addAll(int index, Collection&lt;? extends E&gt; c)，将入参中的元素添加到列表index位置的元素后
12)boolean removeAll(Collection&lt;?&gt; c)，将入参中的所有元素从列表中移除
13)boolean retainAll(Collection&lt;?&gt; c)，将列表中包含入参的元素留下，其他全部移除
14)void clear()，清空列表
15)boolean equals(Object o)，返回当前列表和入参是否相等(入参必须满足是一个List，长度相同，每个元素都相等)
16)int hashCode()，返回列表的hashCode
17)E get(int index)，获取列表中索引位置index的元素
18)E set(int index, E element)，将列表中索引位置index的元素替换为element
19)void add(int index, E element)，将element插入到列表中的index位置(该位置后的元素后移)
20)E remove(int index)，移除列表中index位置的元素
21)int indexOf(Object o)，返回入参o在列表中第一个匹配的位置(如果不存在，返回-1)
22)int indexOf(Object o)，返回入参o在列表中最后一个匹配的位置(如果没找到，返回-1)
23)ListIterator&lt;E&gt; listIterator()，返回一个迭代器
24)ListIterator&lt;E&gt; listIterator(int index)，返回一个列表中从index位置开始的迭代器

      然后我们看一下抽象类AbstractList的实现和要做的事情。AbstractList实现了上边我们描述的List接口，
 并且继承了AbstractCollection类，AbstractCollection提供了Collection层面更加通用的实现，看一下AbstractList的实现：
</code></pre><img src="/typhoon/2018/04/21/list分析/l3.jpg" alt="list" title="list">
<pre><code>我们接着对AbstractList做一下分析：
1)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">public boolean add(E e) &#123;</div><div class="line">       add(size(), e);</div><div class="line">        return true;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>size()是列表的长度，add(E e)也就是在列表结尾增加元素e
2)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">abstract public E get(int index)</div></pre></td></tr></table></figure>
<pre><code>get是一个抽象方法，提供了一个模板留给子类去实现
3)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">public E set(int index, E element) &#123;</div><div class="line">        throw new UnsupportedOperationException();</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>明确声明不支持set操作，也就是说子类必须要自己实现该方法后才能够使用，否则抛异常
4)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">public void add(int index, E element) &#123;</div><div class="line">       throw new UnsupportedOperationException();</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>也是add(e)所依赖的方法，抽象类中不提供具体实现，子类根据需要自己实现
5)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">public E remove(int index) &#123;</div><div class="line">        throw new UnsupportedOperationException();</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>移除指定位置的元素，抽象类不提供实现，子类自己实现
6)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">public int indexOf(Object o) &#123;</div><div class="line">        ListIterator&lt;E&gt; it = listIterator();</div><div class="line">        if (o==null) &#123;</div><div class="line">            while (it.hasNext())</div><div class="line">                if (it.next()==null)</div><div class="line">                    return it.previousIndex();</div><div class="line">        &#125; else &#123;</div><div class="line">            while (it.hasNext())</div><div class="line">                if (o.equals(it.next()))</div><div class="line">                    return it.previousIndex();</div><div class="line">        &#125;</div><div class="line">        return -1;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>查找入参在列表中的位置。首先返回列表的迭代器，如果入参为null，直接遍历列表寻找等于null的元素，如果找到返回位置；
如果入参不为null，遍历列表寻找相等的元素，如果找到返回位置；最后如果没找到返回-1
7)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">public int lastIndexOf(Object o) &#123;</div><div class="line">       ListIterator&lt;E&gt; it = listIterator(size());</div><div class="line">       if (o==null) &#123;</div><div class="line">           while (it.hasPrevious())</div><div class="line">               if (it.previous()==null)</div><div class="line">                   return it.nextIndex();</div><div class="line">       &#125; else &#123;</div><div class="line">           while (it.hasPrevious())</div><div class="line">               if (o.equals(it.previous()))</div><div class="line">                   return it.nextIndex();</div><div class="line">       &#125;</div><div class="line">       return -1;</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>返回入参在列表中的最后匹配的位置。首先返回从列表最后一个元素开始的列表迭代器，如果入参为null，
从尾部向前遍历，找到为null的元素并返回位置；如果入参非null，也是从尾部向首部遍历找到相等的元素并返回位置；如果没有找到返回-1
8)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">public void clear() &#123;</div><div class="line">       removeRange(0, size());</div><div class="line">   &#125;</div><div class="line">   protected void removeRange(int fromIndex, int toIndex) &#123;</div><div class="line">       ListIterator&lt;E&gt; it = listIterator(fromIndex);</div><div class="line">       for (int i=0, n=toIndex-fromIndex; i&lt;n; i++) &#123;</div><div class="line">           it.next();</div><div class="line">           it.remove();</div><div class="line">       &#125;</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>清空列表。返回从索引0开始的列表迭代器，从开始到尾部遍历并且逐个移除元素
9)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">public boolean addAll(int index, Collection&lt;? extends E&gt; c) &#123;</div><div class="line">       rangeCheckForAdd(index);</div><div class="line">       boolean modified = false;</div><div class="line">       for (E e : c) &#123;</div><div class="line">           add(index++, e);</div><div class="line">           modified = true;</div><div class="line">       &#125;</div><div class="line">       return modified;</div><div class="line">   &#125;</div><div class="line">   private void rangeCheckForAdd(int index) &#123;</div><div class="line">       if (index &lt; 0 || index &gt; size())</div><div class="line">           throw new IndexOutOfBoundsException(outOfBoundsMsg(index));</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>将入参集合的元素插入到列表元素index的位置。首先检查index位置是否合法，如果位置&lt;0或者大于长度，下标越界；
然后遍历入参列表，循环在index向后逐个插入元素

10)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">public Iterator&lt;E&gt; iterator() &#123;</div><div class="line">       return new Itr();</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<img src="/typhoon/2018/04/21/list分析/l4.jpg" alt="list" title="list">
<pre><code>返回列表的迭代器。Itr是AbstractList的一个私有内部类，提供了遍历、移除和检查是否有修改的方法
11)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">public ListIterator&lt;E&gt; listIterator(final int index) &#123;</div><div class="line">        rangeCheckForAdd(index);</div><div class="line">        return new ListItr(index);</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>返回从index位置开始的列表迭代器。首先检查index位置是否合法，然后返回一个列表迭代器ListItr，
其实现了ListIterator接口并继承了Itr类，其实也就是提供了列表中任何一个位置元素向前和向后遍历的方式
12)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">public List&lt;E&gt; subList(int fromIndex, int toIndex) &#123;</div><div class="line">        return (this instanceof RandomAccess ?</div><div class="line">               new RandomAccessSubList&lt;&gt;(this, fromIndex, toIndex) :</div><div class="line">                new SubList&lt;&gt;(this, fromIndex, toIndex));</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>截取列表中从fromIndex开始到toIndex结束的子列表。会根据当前列表是不是RandomAccess接口实例，返回不同的子列表实现，
其实可以简单理解为区分ArrayList(实现RandomAccess)和LinkedList(未实现RandomAccess)两种不同的子类实现
13)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">public boolean equals(Object o) &#123;</div><div class="line">        if (o == this)</div><div class="line">            return true;</div><div class="line">        if (!(o instanceof List))</div><div class="line">            return false;</div><div class="line">        ListIterator&lt;E&gt; e1 = listIterator();</div><div class="line">        ListIterator e2 = ((List) o).listIterator();</div><div class="line">        while (e1.hasNext() &amp;&amp; e2.hasNext()) &#123;</div><div class="line">            E o1 = e1.next();</div><div class="line">            Object o2 = e2.next();</div><div class="line">            if (!(o1==null ? o2==null : o1.equals(o2)))</div><div class="line">                return false;</div><div class="line">        &#125;</div><div class="line">        return !(e1.hasNext() || e2.hasNext());</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>检查当前入参是否和当前列表相等。如果满足o==this也就是同一个列表，返回true；如果入参不是List接口实例(类型不匹配)，返回false；
然后获取两个列表的迭代器，并且遍历元素，如果找到相应位置上不相等的元素，直接返回false。while循环的次数取决于两个列表中数量较少的一个，
循环停止后肯定有一个列表到达了结尾，如果这时候还有任何一个列表有元素直接返回false，否则返回true
14)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">public int hashCode() &#123;</div><div class="line">        int hashCode = 1;</div><div class="line">        for (E e : this)</div><div class="line">            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());</div><div class="line">        return hashCode;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>通过遍历元素，根据每一个元素的hashCode累加上一次计算的值乘以31最终得到hashCode(复杂计算为了尽可能减少hashCode重复)

    分析完了List接口和AbstractList抽象类实现，jdk源码中我们最常用到的List实例主要有ArrayList、LinkedList和Vector，
我们逐个做分析。

首先分析一下ArrayList的实现：
</code></pre><img src="/typhoon/2018/04/21/list分析/l5.jpg" alt="list" title="list">
<pre><code>我们抽一些比较常用的方法做一下分析：
1)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">public ArrayList() &#123;</div><div class="line">       super();</div><div class="line">       this.elementData = EMPTY_ELEMENTDATA;</div><div class="line">   &#125;</div><div class="line"> private static final Object[] EMPTY_ELEMENTDATA = &#123;&#125;;</div></pre></td></tr></table></figure>
<pre><code>默认的构造器，我们在编码中经常用到，其实是本质上是创建一个空的Object数组
2)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">public ArrayList(int initialCapacity) &#123;</div><div class="line">       super();</div><div class="line">       if (initialCapacity &lt; 0)</div><div class="line">           throw new IllegalArgumentException(&quot;Illegal Capacity: &quot;+</div><div class="line">                                              initialCapacity);</div><div class="line">       this.elementData = new Object[initialCapacity];</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>带有初始容量的构造器。如果入参小于0报参数非法异常；否则新建一个长度为入参的Object数组并赋值给elementData
3)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">public ArrayList(Collection&lt;? extends E&gt; c) &#123;</div><div class="line">        elementData = c.toArray();</div><div class="line">        size = elementData.length;</div><div class="line">        // c.toArray might (incorrectly) not return Object[] (see 6260652)</div><div class="line">        if (elementData.getClass() != Object[].class)</div><div class="line">            elementData = Arrays.copyOf(elementData, size, Object[].class);</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>入参是一个集合的构造器。先将入参c转变成Object数组赋值给elementData，size变为数组长度；如果赋值后的elementData不是Object数组，
也就是说入参不是Object列表，这时候通过调用Arrays.copyOf方法转变为Object数组
4)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">public E get(int index) &#123;</div><div class="line">      rangeCheck(index);</div><div class="line">      return elementData(index);</div><div class="line">  &#125;</div><div class="line">  private void rangeCheck(int index) &#123;</div><div class="line">     if (index &gt;= size)</div><div class="line">          throw new IndexOutOfBoundsException(outOfBoundsMsg(index));</div><div class="line">  &#125;</div></pre></td></tr></table></figure>
<pre><code>返回指定位置的元素。如果入参大于数组最大索引，报数组越界异常；否则返回指定位置的数组元素
5)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">public E set(int index, E element) &#123;</div><div class="line">        rangeCheck(index);</div><div class="line">        E oldValue = elementData(index);</div><div class="line">        elementData[index] = element;</div><div class="line">        return oldValue;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>将指定位置元素替换为入参元素。先检查是否数组越界，将指定位置元素替换成新元素并返回旧元素
6)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line">public boolean add(E e) &#123;</div><div class="line">        ensureCapacityInternal(size + 1);  // Increments modCount!!</div><div class="line">        elementData[size++] = e;</div><div class="line">        return true;</div><div class="line">    &#125;</div><div class="line">    private void ensureCapacityInternal(int minCapacity) &#123;</div><div class="line">        if (elementData == EMPTY_ELEMENTDATA) &#123;</div><div class="line">            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);</div><div class="line">        &#125;</div><div class="line">        ensureExplicitCapacity(minCapacity);</div><div class="line">    &#125;</div><div class="line">    private void ensureExplicitCapacity(int minCapacity) &#123;</div><div class="line">        modCount++;</div><div class="line">        // overflow-conscious code</div><div class="line">        if (minCapacity - elementData.length &gt; 0)</div><div class="line">            grow(minCapacity);</div><div class="line">    &#125;</div><div class="line">    private void grow(int minCapacity) &#123;</div><div class="line">       // overflow-conscious code</div><div class="line">        int oldCapacity = elementData.length</div><div class="line">        int newCapacity = oldCapacity + (oldCapacity &gt;&gt; 1);</div><div class="line">        if (newCapacity - minCapacity &lt; 0)</div><div class="line">            newCapacity = minCapacity;</div><div class="line">        if (newCapacity - MAX_ARRAY_SIZE &gt; 0)</div><div class="line">            newCapacity = hugeCapacity(minCapacity);</div><div class="line">        // minCapacity is usually close to size, so this is a win:</div><div class="line">        elementData = Arrays.copyOf(elementData, newCapacity);</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>    该方法是ArrayList中最重要的方法，也是最复杂的方法，功能就是新增元素在内部数组的尾部。
中间用到了一些扩容和数组复制的方法也都贴了出了，接下来对其逐步详细分解。首先要保证当前数组容量至少是当前列表元素个数加1，
如果不满足要进行扩容，然后在数组中原来列表尾部索引加1的位置填充入参e；
扩容方法ensureCapacityInternal中如果当前数组是空(说明是使用默认构造器新建列表，第一次新增元素)，
最小容量为默认初始容量private static final int DEFAULT_CAPACITY = 10和入参中较大的一个，然后调用ensureExplicitCapacity 
保证数组长度至少为minCapacity；ensureExplicitCapacity 方法中如果最小空间需求量大于当前数组长度，调用grow 方法扩容数组长度至少为minCapacity；
grow 方法中，先存储数组的旧长度oldCapacity，暂定新长度newCapacity为旧长度的3/2倍，如果新长度没有最小长度需求minCapacity大，
将minCapacity赋值给新长度newCapacity，如果此时的新长度比默认最大数组长度MAX_ARRAY_SIZE大，将Integer最大值赋值给新长度newCapacity，
然后将旧数组中的元素复制到新长度的数组中(Arrays.copyOf底层调用System.arraycopy方法）
7)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">public E remove(int index) &#123;</div><div class="line">        rangeCheck(index);</div><div class="line">        modCount++;</div><div class="line">        E oldValue = elementData(index);</div><div class="line">        int numMoved = size - index - 1;</div><div class="line">        if (numMoved &gt; 0)</div><div class="line">            System.arraycopy(elementData, index+1, elementData, index,</div><div class="line">                             numMoved);</div><div class="line">        elementData[--size] = null; // clear to let GC do its work</div><div class="line">       return oldValue;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>    该方法是移除列表中index位置的元素。首先检查是否下标越界；然后modCount加1；接着用oldValue存储该位置的旧元素，
numberMoved记录的是数组中从index位置以后所有需要移动的元素个数；如果需要移动元素个数大于0(index不是数组尾部元素)，
将数组elementData 中的index+1位置以后的numMoved个元素拷贝到elementData 数组中index位置以后numMoved个元素位置，也就是覆盖，
效果就是index后的元素向前移动一位，完成删除elementData(index)的效果
8)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">public void clear() &#123;</div><div class="line">        modCount++;</div><div class="line">        // clear to let GC do its work</div><div class="line">        for (int i = 0; i &lt; size; i++)</div><div class="line">            elementData[i] = null;</div><div class="line">        size = 0;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>    清空列表中的元素。其实就是遍历elementData数组，将其每一个索引位置指向null，然后把size变成0。
注意：for循环上边有段注释// clear to let GC do its work，什么意思呢，其实我们循环中把数组中的元素都指向null，
那么原来开辟的数组元素指向的内存空间已经失去引用，GC回收的时候就可以回收这些空间了

     以上我们详细分析了ArrayList的代码以及核心的一些方法。总结出一下几点：
1)ArrayList底层由数组实现
2)get查询的时候，是随机访问，也就是直接通过数组指针到内存中获取元素值，不会遍历列表
3)新增和移除成本比较大。如果列表已经很大，那么在0号位置新增或删除元素会移动size-1个元素，
  在jvm层面就是新开辟内存空间存放元素，GC回收失去索引的旧空间
接着我们分析List接口另一个实现Vector：
</code></pre><img src="/typhoon/2018/04/21/list分析/l6.jpg" alt="list" title="list">
<pre><code>    从代码接够以及源码我们可以看到，Vector实现和ArrayList基本一样，只不过对大部分方法强制加上synchronized关键字，
也就是线程阻塞访问，和HashTable的做法一样，现在已经基本废弃，这里不再做过多的分析。

    然后我们最后一个要分析的List接口实现类，也就是经常被用来和ArrayList做各种比较的LinkedList，我们先看一下代码结构：
</code></pre><img src="/typhoon/2018/04/21/list分析/l7.jpg" alt="list" title="list">
<pre><code>    在分析源码之前，我们从方法结构中看到了LinkedList有很多和ArrayList不一样的方法，比如说peek(),poll(),offer(),pop()都是队列中拥有的方法，
我们猜测LinkedList应该实现了队列的相关接口。看一下LinkedList的声明：
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">public class LinkedList&lt;E&gt;</div><div class="line">    extends AbstractSequentialList&lt;E&gt;</div><div class="line">    implements List&lt;E&gt;, Deque&lt;E&gt;, Cloneable, java.io.Serializable</div></pre></td></tr></table></figure>
<pre><code>    很明显，LinkedList继承了抽象类AbstractSequentialList并且实现了List和Deque接口，AbstractSequentialList继承了AbstractList并提供了一些通用实现，
实现了Deque(Deque继承了Queue接口)，也就是说LinkedList拥有从头部和尾部遍历的能力，我们分析一下LinkedList一下常用的方法：
1)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line">public E getFirst() &#123;</div><div class="line">       final Node&lt;E&gt; f = first;</div><div class="line">      if (f == null)</div><div class="line">           throw new NoSuchElementException();</div><div class="line">       return f.item;</div><div class="line">   &#125;</div><div class="line">   private static class Node&lt;E&gt; &#123;</div><div class="line">       E item;</div><div class="line">       Node&lt;E&gt; next;</div><div class="line">       Node&lt;E&gt; prev;</div><div class="line">       Node(Node&lt;E&gt; prev, E element, Node&lt;E&gt; next) &#123;</div><div class="line">           this.item = element;</div><div class="line">           this.next = next;</div><div class="line">           this.prev = prev;</div><div class="line">       &#125;</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>    获取列表的第一个元素。该方法是Deque中定义，首先获取第一个Node节点，如果为空(暂时没有元素)抛出异常，否则返回第一个元素的值；
接着看到Node是LinkedList中的一个私有静态内部类，存储了当前节点的值以及前后节点的指针，可以得知LinkedList的存储结构是链表，大致如下：
</code></pre><img src="/typhoon/2018/04/21/list分析/l9.jpg" alt="list" title="list">
<pre><code>2)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">public E getLast() &#123;</div><div class="line">       final Node&lt;E&gt; l = last;</div><div class="line">       if (l == null)</div><div class="line">           throw new NoSuchElementException();</div><div class="line">       return l.item;</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>返回列表中最后一个元素。如果没有元素抛出异常，否则返回最后一个元素的内容
3)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line">public E removeFirst() &#123;</div><div class="line">       final Node&lt;E&gt; f = first;</div><div class="line">       if (f == null)</div><div class="line">          throw new NoSuchElementException();</div><div class="line">      return unlinkFirst(f);</div><div class="line">   &#125;</div><div class="line">   private E unlinkFirst(Node&lt;E&gt; f) &#123;</div><div class="line">       // assert f == first &amp;&amp; f != null;</div><div class="line">      final E element = f.item;</div><div class="line">       final Node&lt;E&gt; next = f.next;</div><div class="line">       f.item = null;</div><div class="line">       f.next = null; // help GC</div><div class="line">       first = next;</div><div class="line">       if (next == null)</div><div class="line">           last = null;</div><div class="line">       else</div><div class="line">           next.prev = null;</div><div class="line">       size--;</div><div class="line">       modCount++;</div><div class="line">       return element;</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>    移除列表中第一个元素。如果列表为空，报异常；否则调用unlinkFirst方法解除指针指向；unlinkFirst方法中先记录首元素内容element，
然后记录下一个元素next，将首节点内容指向null(GC回收)，后指针指向改为null，然后把第二个节点next置为first，如果next为null，
说明原来列表中只有一个Node节点，把last也置为null，否则把next的前节点置为null，然后把size减1，最后返回旧节点内容element。其实流程大概如下：
</code></pre><img src="/typhoon/2018/04/21/list分析/l10.jpg" alt="list" title="list">
<pre><code>这样就完成首节点移除操作
4)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">public E removeLast() &#123;</div><div class="line">        final Node&lt;E&gt; l = last;</div><div class="line">        if (l == null)</div><div class="line">            throw new NoSuchElementException();</div><div class="line">        return unlinkLast(l);</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>移除最后一个节点。类似3中的操作，不再做详细分析
5)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">public void addFirst(E e) &#123;</div><div class="line">       linkFirst(e);</div><div class="line">   &#125;</div><div class="line">   private void linkFirst(E e) &#123;</div><div class="line">       final Node&lt;E&gt; f = first;</div><div class="line">       final Node&lt;E&gt; newNode = new Node&lt;&gt;(null, e, f);</div><div class="line">       first = newNode;</div><div class="line">       if (f == null)</div><div class="line">           last = newNode;</div><div class="line">       else</div><div class="line">           f.prev = newNode;</div><div class="line">       size++;</div><div class="line">       modCount++;</div><div class="line">   &#125;</div></pre></td></tr></table></figure>
<pre><code>将给定元素插入到列表第一个位置。linkFirst方法中f暂存首节点first，然后根据入参e新建一个prev指针null，next指针为f的节点，
然后把新节点赋值给first，如果f为null(之前没有元素)，last指针也指向新节点；否则原来first节点的元素prev指针指向新节点，然后增加size大小。

以上都是LinkedList特有的方法，接下来我们分析一下List接中有的方法
6)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">public E get(int index) &#123;</div><div class="line">      checkElementIndex(index);</div><div class="line">      return node(index).item;</div><div class="line">  &#125;</div><div class="line">  private void checkElementIndex(int index) &#123;</div><div class="line">      if (!isElementIndex(index))</div><div class="line">          throw new IndexOutOfBoundsException(outOfBoundsMsg(index));</div><div class="line">  &#125;</div><div class="line">  private boolean isElementIndex(int index) &#123;</div><div class="line">      return index &gt;= 0 &amp;&amp; index &lt; size;</div><div class="line">  &#125;</div><div class="line">  Node&lt;E&gt; node(int index) &#123;</div><div class="line">      // assert isElementIndex(index);</div><div class="line">      if (index &lt; (size &gt;&gt; 1)) &#123;</div><div class="line">          Node&lt;E&gt; x = first;</div><div class="line">          for (int i = 0; i &lt; index; i++)</div><div class="line">              x = x.next;</div><div class="line">          return x;</div><div class="line">      &#125; else &#123;</div><div class="line">          Node&lt;E&gt; x = last;</div><div class="line">          for (int i = size - 1; i &gt; index; i--)</div><div class="line">              x = x.prev;</div><div class="line">          return x;</div><div class="line">      &#125;</div><div class="line">  &#125;</div></pre></td></tr></table></figure>
<pre><code>get方法是List中定义的获取指定位置元素的方法。首先检查索引是否合法（&gt;=0&amp;&amp;&lt;size）;然后调用node方法查找元素，由于是链表结构，无法直接通过index定位元素，
如果index &lt; size&gt;&gt;1(index在size前半部分)，从开始节点first节点遍历到index位置返回内容；否则(index在size后半部分)从结尾节点last向前遍历到index位置返回内容。
    此处可以看出LinkedList对于查找性能不是太好，不像ArrayList直接通过index定位到内存中的元素，由此可知在查询方面（随机访问）性能不如ArrayList

7)
</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">public boolean add(E e) &#123;</div><div class="line">        linkLast(e);</div><div class="line">        return true;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<pre><code>同样对List接口中add方法的实现，显得很简单，为什么呢？因为从linkLast方法中我们直接找到last节点然后修改next指针指向我们新元素，把新元素的prev节点指向last节点，
最后把last指针指向新节点就好了，中间不牵扯类似ArrayList中的扩容和数组复制问题。此处可以看出LinkedList对于新增节点的性能要优于ArrayList  


    经过上述一些列的分析，我们队List的三种常见实现类有了更深刻的认识和了解。接下来我们就日常开发中经常纠结的ArrayList和LinkedList查询和插入到底哪个性能比较好展开
进一步的实验和验证，运行一下例子：
</code></pre><img src="/typhoon/2018/04/21/list分析/l11.jpg" alt="list" title="list">
<pre><code>    为了将效果变得明显，我们向两个list中都增加了1000000个元素，然后测试get性能。细心的人发现为什么两次测试效果不一样呢，看一下get方法的索引，
第一次我们测试通过索引为999999，第二次索引位置是500000，也就是说第一个是查询列表中最后一个元素，第二次是查询列表中中间位置的元素，
为什么性能差异那么大呢？ArrayList的get方法就不用看了，看一下LinkedList中的get方法，有这么一段：
</code></pre><img src="/typhoon/2018/04/21/list分析/l12.jpg" alt="list" title="list">
<pre><code>    就是如果遍历的方式依赖于index大小，如果index不满足index&lt;(size&gt;&gt;1)，遍历查询的时候会走else分支，结合我们例子，size为1000000，
index为999999(最后一个元素)，那么会从最后一个元素遍历，凑巧一下子找到了元素，这种情况下性能是和ArrayList中的get性能一样的；然后index为500000得时候，
ArrayList和之前get性能基本一样，而LinkedList会走else分支从列表中最后一个节点向前遍历，但是index是在此段的最后一个元素，
也就是说LinkedList将近遍历了500000次才找到元素，这也就成为了性能差别的原因。

    然后我们修改上边例子中的代码测试插入效果：
</code></pre><img src="/typhoon/2018/04/21/list分析/l14.jpg" alt="list" title="list">
<pre><code>    可以看到耗时是一样的，为什么呢？因为add(e)方法对于LinkedList只需要新建Node节点和改变指针指向，而ArrayList会将size加1然后将数组最后一个元素指针
指向新元素如果没有出现扩容和数组赋值，这种操作对于两种List基本没有性能差别。
    我们把上述的代码改一下，然后再运行：
</code></pre>
<pre><code>    为了让效果更明显，我们把初始容量增大成10000000，可以看到LinkedList.add(0,111111)基本没有耗时，而ArrayList.add(0,111111)耗时3，性能差别很明显，为什么呢？
对于前者，仍然只需要新建一个Node和改变前后指针指向，而后者会发生数组复制，将原数组所有元素拷贝到自己从第二个位开始，长度为size的对应位置，
然后将入参赋值给0号位置，出了数组复制，还可能出现扩容，所以性能一定会比 LinkedList差。

    此篇我们队Jdk集合中List以及常用实现做了详细的分析和性能对比，希望帮助大家在实际开发中根据具体的业务场景选用不同的List实现，从而带来性能提升。
如果有觉得分析不到位或者理解有偏差的，可以直接留言或者私聊我。
</code></pre><h5 id="原创不易，请多多支持！"><a href="#原创不易，请多多支持！" class="headerlink" title="原创不易，请多多支持！"></a>原创不易，请多多支持！</h5><pre><code>附带公众号：
</code></pre><img src="/typhoon/2018/04/21/list分析/webchat.jpg" alt="list" title="list">
  
	</div>
		<footer class="article-footer clearfix">
<div class="article-catetags">

<div class="article-categories">
  <span></span>
  <a class="article-category-link" href="/typhoon/categories/java性能优化/">java性能优化</a>
</div>


  <div class="article-tags">
  
  <span></span> <a href="/typhoon/tags/java性能优化/">java性能优化</a>
  </div>

</div>



	<div class="article-share" id="share">
	
	  <div data-url="http://scorpioaeolus.oschina.io/2018/04/21/list分析/" data-title="jdk源码分析之List--常用实现类分析与对比 | Typhoon&#39;s code space" data-tsina="null" class="share clearfix">
	  </div>
	
	</div>


</footer>

   	       
	</article>
	
<nav class="article-nav clearfix">
 
 <div class="prev" >
 <a href="/typhoon/2018/04/21/cas乐观锁/" title="jdk源码分析之原子变量AtomicInteger--乐观锁与CAS以及问题">
  <strong>上一篇：</strong><br/>
  <span>
  jdk源码分析之原子变量AtomicInteger--乐观锁与CAS以及问题</span>
</a>
</div>


<div class="next">
<a href="/typhoon/2018/04/21/integer缓存/"  title="jdk源码分析之Integer--缓存">
 <strong>下一篇：</strong><br/> 
 <span>jdk源码分析之Integer--缓存
</span>
</a>
</div>

</nav>

	


</div>  
      <div class="openaside"><a class="navbutton" href="#" title="Show Sidebar"></a></div>

  <div id="toc" class="toc-aside">
  <strong class="toc-title">Contents</strong>
 
 <ol class="toc"><li class="toc-item toc-level-5"><a class="toc-link" href="#原创不易，请多多支持！"><span class="toc-number">1.</span> <span class="toc-text">原创不易，请多多支持！</span></a></li></ol>
 
  </div>

<div id="asidepart">
<div class="closeaside"><a class="closebutton" href="#" title="Hide Sidebar"></a></div>
<aside class="clearfix">

  


  
<div class="categorieslist">
	<p class="asidetitle">Categories</p>
		<ul>
		
		  
			<li><a href="/typhoon/categories/dubbo/" title="dubbo">dubbo<sup>8</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/java性能优化/" title="java性能优化">java性能优化<sup>17</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/java源码分析/" title="java源码分析">java源码分析<sup>1</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/motan/" title="motan">motan<sup>2</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/spring/" title="spring">spring<sup>11</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/springboot/" title="springboot">springboot<sup>28</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/springmvc/" title="springmvc">springmvc<sup>1</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/容器/" title="容器">容器<sup>1</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/工具/" title="工具">工具<sup>7</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/性能优化/" title="性能优化">性能优化<sup>5</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/架构/" title="架构">架构<sup>8</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/案例分析/" title="案例分析">案例分析<sup>13</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/缓存/" title="缓存">缓存<sup>4</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/设计模式/" title="设计模式">设计模式<sup>3</sup></a></li>
		  
		
		  
			<li><a href="/typhoon/categories/面试题/" title="面试题">面试题<sup>1</sup></a></li>
		  
		
		</ul>
</div>


  
<div class="tagslist">
	<p class="asidetitle">Tags</p>
		<ul class="clearfix">
		
			
				<li><a href="/typhoon/tags/springboot/" title="springboot">springboot<sup>28</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/java性能优化/" title="java性能优化">java性能优化<sup>9</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/限流/" title="限流">限流<sup>3</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/Spring5/" title="Spring5">Spring5<sup>3</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/设计模式/" title="设计模式">设计模式<sup>3</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/案例分析/" title="案例分析">案例分析<sup>2</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/性能优化/" title="性能优化">性能优化<sup>2</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/Spring/" title="Spring">Spring<sup>2</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/dubbo/" title="dubbo">dubbo<sup>2</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/分页/" title="分页">分页<sup>2</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/并发/" title="并发">并发<sup>2</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/异常拦截/" title="异常拦截">异常拦截<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/dubbo分布式事务/" title="dubbo分布式事务">dubbo分布式事务<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/自带图片/" title="自带图片">自带图片<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/svn导出mvn项目/" title="svn导出mvn项目">svn导出mvn项目<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/dubbo过滤器/" title="dubbo过滤器">dubbo过滤器<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/排序性能对比/" title="排序性能对比">排序性能对比<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/ListenableFuture/" title="ListenableFuture">ListenableFuture<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/PropertyChangeListener/" title="PropertyChangeListener">PropertyChangeListener<sup>1</sup></a></li>
			
		
			
				<li><a href="/typhoon/tags/jdbcTemplate高可用/" title="jdbcTemplate高可用">jdbcTemplate高可用<sup>1</sup></a></li>
			
		
		</ul>
</div>


  <div class="linkslist">
  <p class="asidetitle">Links</p>
    <ul>
        
          <li>
            
            	<a href="https://coderq.com" target="_blank" title="一个面向程序员交流分享的新一代社区">码农圈</a>
            
          </li>
        
          <li>
            
            	<a href="http://wuchong.me" target="_blank" title="Jark&#39;s Blog">Jark&#39;s Blog</a>
            
          </li>
        
    </ul>
</div>

  


  <div class="rsspart">
	<a href="/atom.xml" target="_blank" title="rss">RSS</a>
</div>

  <div class="weiboshow">
  <p class="asidetitle">Weibo</p>
    <iframe width="100%" height="119" class="share_self"  frameborder="0" scrolling="no" src="http://widget.weibo.com/weiboshow/index.php?language=&width=0&height=119&fansRow=2&ptype=1&speed=0&skin=9&isTitle=1&noborder=1&isWeibo=0&isFans=0&uid=null&verifier=b3593ceb&dpc=1"></iframe>
</div>


</aside>
</div>
    </div>
    <footer><div id="footer" >
	
	<div class="line">
		<span></span>
		<div class="author"></div>
	</div>
	
	
	<section class="info">
		<p> Hello ,I&#39;m a java coder. <br/>
			This is my blog,believe it or not.</p>
	</section>
	 
	<div class="social-font" class="clearfix">
		
		
		
		
		
		
		
		
		
		
		<a href="mailto:ScorpioAeolus@163.com" target="_blank" class="icon-email" title="Email Me"></a>
		
	</div>
			
		

		<p class="copyright">
		Powered by <a href="http://hexo.io" target="_blank" title="hexo">hexo</a> and Theme by <a href="https://github.com/wuchong/jacman" target="_blank" title="Jacman">Jacman</a> © 2019 
		
		<a href="/typhoon/about" target="_blank" title="typhoon">typhoon</a>
		
		
		</p>
</div>
</footer>
    <script src="/typhoon/js/jquery-2.0.3.min.js"></script>
<script src="/typhoon/js/jquery.imagesloaded.min.js"></script>
<script src="/typhoon/js/gallery.js"></script>
<script src="/typhoon/js/jquery.qrcode-0.12.0.min.js"></script>

<script type="text/javascript">
$(document).ready(function(){ 
  $('.navbar').click(function(){
    $('header nav').toggleClass('shownav');
  });
  var myWidth = 0;
  function getSize(){
    if( typeof( window.innerWidth ) == 'number' ) {
      myWidth = window.innerWidth;
    } else if( document.documentElement && document.documentElement.clientWidth) {
      myWidth = document.documentElement.clientWidth;
    };
  };
  var m = $('#main'),
      a = $('#asidepart'),
      c = $('.closeaside'),
      o = $('.openaside');
  c.click(function(){
    a.addClass('fadeOut').css('display', 'none');
    o.css('display', 'block').addClass('fadeIn');
    m.addClass('moveMain');
  });
  o.click(function(){
    o.css('display', 'none').removeClass('beforeFadeIn');
    a.css('display', 'block').removeClass('fadeOut').addClass('fadeIn');      
    m.removeClass('moveMain');
  });
  $(window).scroll(function(){
    o.css("top",Math.max(80,260-$(this).scrollTop()));
  });
  
  $(window).resize(function(){
    getSize(); 
    if (myWidth >= 1024) {
      $('header nav').removeClass('shownav');
    }else{
      m.removeClass('moveMain');
      a.css('display', 'block').removeClass('fadeOut');
      o.css('display', 'none');
      
      $('#toc.toc-aside').css('display', 'none');
        
    }
  });
});
</script>

<script type="text/javascript">
$(document).ready(function(){ 
  var ai = $('.article-content>iframe'),
      ae = $('.article-content>embed'),
      t  = $('#toc'),
      ta = $('#toc.toc-aside'),
      o  = $('.openaside'),
      c  = $('.closeaside');
  if(ai.length>0){
    ai.wrap('<div class="video-container" />');
  };
  if(ae.length>0){
   ae.wrap('<div class="video-container" />');
  };
  c.click(function(){
    ta.css('display', 'block').addClass('fadeIn');
  });
  o.click(function(){
    ta.css('display', 'none');
  });
  $(window).scroll(function(){
    ta.css("top",Math.max(140,320-$(this).scrollTop()));
  });
});
</script>


<script type="text/javascript">
$(document).ready(function(){ 
  var $this = $('.share'),
      url = $this.attr('data-url'),
      encodedUrl = encodeURIComponent(url),
      title = $this.attr('data-title'),
      tsina = $this.attr('data-tsina'),
      description = $this.attr('description');
  var html = [
  '<div class="hoverqrcode clearfix"></div>',
  '<a class="overlay" id="qrcode"></a>',
  '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="article-share-facebook" target="_blank" title="Facebook"></a>',
  '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="article-share-twitter" target="_blank" title="Twitter"></a>',
  '<a href="#qrcode" class="article-share-qrcode" title="微信"></a>',
  '<a href="http://widget.renren.com/dialog/share?resourceUrl=' + encodedUrl + '&srcUrl=' + encodedUrl + '&title=' + title +'" class="article-share-renren" target="_blank" title="人人"></a>',
  '<a href="http://service.weibo.com/share/share.php?title='+title+'&url='+encodedUrl +'&ralateUid='+ tsina +'&searchPic=true&style=number' +'" class="article-share-weibo" target="_blank" title="微博"></a>',
  '<span title="Share to"></span>'
  ].join('');
  $this.append(html);

  $('.hoverqrcode').hide();

  var myWidth = 0;
  function updatehoverqrcode(){
    if( typeof( window.innerWidth ) == 'number' ) {
      myWidth = window.innerWidth;
    } else if( document.documentElement && document.documentElement.clientWidth) {
      myWidth = document.documentElement.clientWidth;
    };
    var qrsize = myWidth > 1024 ? 200:100;
    var options = {render: 'image', size: qrsize, fill: '#2ca6cb', text: url, radius: 0.5, quiet: 1};
    var p = $('.article-share-qrcode').position();
    $('.hoverqrcode').empty().css('width', qrsize).css('height', qrsize)
                          .css('left', p.left-qrsize/2+20).css('top', p.top-qrsize-10)
                          .qrcode(options);
  };
  $(window).resize(function(){
    $('.hoverqrcode').hide();
  });
  $('.article-share-qrcode').click(function(){
    updatehoverqrcode();
    $('.hoverqrcode').toggle();
  });
  $('.article-share-qrcode').hover(function(){}, function(){
      $('.hoverqrcode').hide();
  });
});   
</script>









<link rel="stylesheet" href="/typhoon/fancybox/jquery.fancybox.css" media="screen" type="text/css">
<script src="/typhoon/fancybox/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
$(document).ready(function(){ 
  $('.article-content').each(function(i){
    $(this).find('img').each(function(){
      if ($(this).parent().hasClass('fancybox')) return;
      var alt = this.alt;
      if (alt) $(this).after('<span class="caption">' + alt + '</span>');
      $(this).wrap('<a href="' + this.src + '" title="' + alt + '" class="fancybox"></a>');
    });
    $(this).find('.fancybox').each(function(){
      $(this).attr('rel', 'article' + i);
    });
  });
  if($.fancybox){
    $('.fancybox').fancybox();
  }
}); 
</script>



<!-- Analytics Begin -->



<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "//hm.baidu.com/hm.js?e6d1f421bbc9962127a50488f9ed37d1";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>



<!-- Analytics End -->

<!-- Totop Begin -->

	<div id="totop">
	<a title="Back to Top"><img src="/typhoon/img/scrollup.png"/></a>
	</div>
	<script src="/typhoon/js/totop.js"></script>

<!-- Totop End -->

<!-- MathJax Begin -->
<!-- mathjax config similar to math.stackexchange -->


<!-- MathJax End -->

<!-- Tiny_search Begin -->

<!-- Tiny_search End -->

  </body>
</html>
